/*
 * 部分参考RT-Thread
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
*/

/**
 * Copyright (c) 2006-2020, zwl
 * 
 * description 对象操作函数
 * 
 * Change Logs:
 * Date             Author         Notes
 * 2021-01-08       Zwl             创建
 * 
 */
#include "EntTypeFramework.h"
#include "object.h"
#include "Device.h"
#include "Coroutine.h"
#include "Event.h"
#include "Timer.h"



//对象类型与索引
enum rt_object_info_type{
#if ETF_DEVICE_EN
    ETF_Object_Info_Device       = 0,                   /**< The object is a device */
#endif

#if ETF_COROUTINE_EN
    ETF_Object_Info_Coroutine,                    		/**< The object is a coroutine */
#endif

#if ETF_EVENT_EN
    ETF_Object_Info_Event,                              /**< 对象类型是事件. */
#endif
    
#if ETF_TIMER_EN
    ETF_Object_Info_Timer,                              /**< 对象类型是定时器. */
#endif

    ETF_Object_Info_Unknown,                            /**< The object is unknown. */
};


#define _OBJ_CONTAINER_RUN_LIST_INIT(c)         {&(etf_object_container[c].object_run_list), &(etf_object_container[c].object_run_list)}
#define _OBJ_CONTAINER_SUSPEND_LIST_INIT(c)     {&(etf_object_container[c].object_suspend_list), &(etf_object_container[c].object_suspend_list)}


//对象容器[数组]
static struct etf_object_information etf_object_container[ETF_Object_Info_Unknown] =
{
#if ETF_DEVICE_EN
    /* initialize object container - device */
    {ETF_Object_Class_Device, _OBJ_CONTAINER_RUN_LIST_INIT(ETF_Object_Info_Device), _OBJ_CONTAINER_SUSPEND_LIST_INIT(ETF_Object_Info_Device), sizeof(struct etf_device)},
#endif

#if ETF_COROUTINE_EN
    {ETF_Object_Class_Coroutine, _OBJ_CONTAINER_RUN_LIST_INIT(ETF_Object_Info_Coroutine), _OBJ_CONTAINER_SUSPEND_LIST_INIT(ETF_Object_Info_Coroutine), sizeof(struct etf_co_tcb)},
#endif

#if ETF_EVENT_EN
    {ETF_Object_Class_Event, _OBJ_CONTAINER_RUN_LIST_INIT(ETF_Object_Info_Event), _OBJ_CONTAINER_SUSPEND_LIST_INIT(ETF_Object_Info_Event), sizeof(struct etf_event)},
#endif

#if ETF_TIMER_EN
    {ETF_Object_Class_Timer, _OBJ_CONTAINER_RUN_LIST_INIT(ETF_Object_Info_Timer), _OBJ_CONTAINER_SUSPEND_LIST_INIT(ETF_Object_Info_Timer), sizeof(struct etf_timer)},
#endif



};

/**
 *  从对象容器中获取对应类型对象的链表首地址
 *
 *@param :  type：对象类型
 *
 *@return:  对象链表首地址
 *
 *@note  : 
 *
 *
 */
struct etf_object_information * etf_object_get_information(enum etf_object_class_type type){
//    int index;
//
//    for (index = 0; index < ETF_Object_Info_Unknown; index ++){
//        if (etf_object_container[index].type == type){ 
//            return &etf_object_container[index];
//        }
//    }

    if( (0 == (etf_uint8_t)type) || ((etf_uint8_t)ETF_Object_Info_Unknown <= ((etf_uint8_t)type-1)) ){
        return ETF_NULL;
    } else {
        return &etf_object_container[(etf_uint8_t)type-1];
    }
}

/**
 *  静态对象初始化
 *
 *@param :  object：要初始化的对象；
 *          type：对象类型；
 *          name：对象名；
 *@return:
 *
 *@note  : 
 *          插入到对象容器相应类型的链表中
 *
 */
void etf_object_init(struct etf_object *object, enum etf_object_class_type type, const char *name){

    struct etf_list_node *                  node                = ETF_NULL;
    struct etf_object_information           *information;

    /* 从对象容器中获得对应类型的节点头 */
    information                                                 = etf_object_get_information(type);
    ETF_IN_ASSERT(information != ETF_NULL);

    /* 查找要初始化的对象是否已经存在 */
//    ETF_IN_ASSERT( (!((object->type & ETF_Object_Class_Static) && (ETF_Object_list_state_null != object->state) )) );
    for(node  = information->object_run_list.next; node != &(information->object_run_list); node  = node->next){
        struct etf_object *                 obj;

        obj                                                     = etf_list_entry(node, struct etf_object, list);
        
        if(obj){
            //是否相等，已经存在
            ETF_IN_ASSERT(obj != object);
        }
    }
    
    for(node  = information->object_suspend_list.next; node != &(information->object_suspend_list); node  = node->next){
        struct etf_object *                 obj;

        obj                                                     = etf_list_entry(node, struct etf_object, list);
        
        if(obj){
            //是否相等，已经存在
            ETF_IN_ASSERT(obj != object);
        }
    }

    //初始化参数，设备为静态，标志被初始化
    object->type                                                = object->type | type |ETF_Object_Class_Static;
    //设置对象名
    etf_strncpy(object->name, name, ETF_OBJ_NAME_MAX);

    //对象插入到对象容器相应类型的挂起链表中
//    etf_list_insert_after(&(information->object_list), &(object->list));
    ETF_LIST_INSERT_AFTER_SUSPEND_LIST(information, object);
}

/**
 * 对象从对象容器列表中分离
 * 
 *@param :  object：要分离的对象
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
void etf_object_detach(etf_object_t object){


    /* 对象检查 */
    ETF_IN_ASSERT(object != ETF_NULL);


    /* 对象类型设置为默认 */
    object->type                                                = object->type&(~ETF_Object_Class_Static);

    /* 改变对象状态 */
    object->state                                               = ETF_Object_list_state_null;
    
    /* 从链表中移除对象 */
    etf_list_remove(&(object->list));
}

/**
 * 获取对象类型
 *
 *@param :  object：需要获取类型的对象
 *
 *@return:  对象类型
 *
 *@note  : 
 *
 *
 */
etf_uint8_t etf_object_get_type(etf_object_t object){
    /* object check */
    ETF_IN_ASSERT(object != ETF_NULL);

    return object->type & ~ETF_Object_Class_Static;
}

/**
 *  获取对象当前状态，运行或挂起
 *
 *@param :  object：需要获取类型的对象
 *
 *@return:  状态
 *
 *@note  : 
 *
 *
 */
enum etf_object_list_state_type etf_object_get_state(etf_object_t object){

    /* object check */
    ETF_IN_ASSERT(object != ETF_NULL);

    /* 是否初始化过 */
    if ( !(object->type & ETF_Object_Class_Static) )
        return ETF_Object_list_state_null;

    return object->state;
}


/**
 * 检查对象是否是系统对象(是否已经注册到对象容器中，通过对象初始化函数)
 *
 *@param :  object：要检查的对象
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
etf_bool_t etf_object_is_systemobject(etf_object_t object){
    /* object check */
    ETF_IN_ASSERT(object != ETF_NULL);

    if (object->type & ETF_Object_Class_Static)
        return ETF_TRUE;

    return ETF_FALSE;
}

/**
 *  切换对象到运行链表中
 *
 *@param :  object：需要切换的对象；
 *
 *@return:  结果；
 *
 *@note  : 
 *
 *
 */
etf_err_t etf_object_change_to_run_list(etf_object_t object){

    struct etf_object_information           *information;

//    /* object check */
//    ETF_IN_ASSERT(object != ETF_NULL);
//    /* 是否初始化过 */
//    ETF_IN_ASSERT(object->type & ETF_Object_Class_Static);
    
    /* 从对象容器中获得对应类型的节点头 */
    information                                                 = etf_object_get_information( (enum etf_object_class_type)(object->type & (~ETF_Object_Class_Static)) );
    ETF_IN_ASSERT(information != ETF_NULL);

    /* 没有插入到任何链表中 */
    if(ETF_Object_list_state_null == object->state){
        return (-ETF_ERROR);
    }

    /* 当前是否在挂起链表中 */
    if(ETF_Object_list_state_suspend_list == object->state){
        /* 删除节点 */
        ETF_IRQ_DISABLE();
        etf_object_detach(object);
        ETF_IRQ_ENABLE();
        /* 插入到运行链表中 */
        ETF_LIST_INSERT_AFTER_RUN_LIST(information, object);
    }

    return ETF_EOK;
}

/**
 *  切换对象到挂起链表中
 *
 *@param :  object：需要切换的对象；
 *
 *@return:  结果；
 *
 *@note  : 
 *
 *
 */
etf_err_t etf_object_change_to_suspend_list(etf_object_t object){

    struct etf_object_information           *information;

    /* object check */
    ETF_IN_ASSERT(object != ETF_NULL);
    /* 是否初始化过 */
    ETF_IN_ASSERT(object->type & ETF_Object_Class_Static);
    
    /* 从对象容器中获得对应类型的节点头 */
    information                                                 = etf_object_get_information( (enum etf_object_class_type)(object->type & (~ETF_Object_Class_Static)) );
    ETF_IN_ASSERT(information != ETF_NULL);

    /* 没有插入到任何链表中 */
    if(ETF_Object_list_state_null == object->state){
        return (-ETF_ERROR);
    }

    /* 当前是否在运行链表中 */
    if(ETF_Object_list_state_run_list == object->state){
        /* 删除节点 */
        ETF_IRQ_DISABLE();
        etf_object_detach(object);

        ETF_IRQ_ENABLE();
        /* 插入到挂起链表中 */
        ETF_LIST_INSERT_AFTER_SUSPEND_LIST(information, object);
    }

    return ETF_EOK;
}


